package com.vegetable.modules.controller.stock;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.R;
import com.vegetable.modules.entity.stock.CostWeightChangeSource;
import com.vegetable.modules.entity.stock.to.CostWeightChangeQueryTO;
import com.vegetable.modules.service.stock.ICostWeightChangeQueryService;
import com.vegetable.modules.service.stock.IChainViewService;
import com.vegetable.modules.service.stock.ICostWeightChangeChainService;
import com.vegetable.modules.service.stock.ICostWeightChangeSourceService;
import com.vegetable.modules.vo.CostWeightChangeChainVO;
import com.vegetable.modules.vo.CostWeightChangeGroupVO;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 * 成本单价变化记录控制器
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-21
 */
@Slf4j
@RestController
@RequestMapping("/stock/costWeightChange")
@Api(tags = "成本单价变化记录")
public class CostWeightChangeController {

    @Resource
    private ICostWeightChangeQueryService costWeightChangeQueryService;
    
    @Resource
    private IChainViewService chainViewService;
    
    @Resource
    private ICostWeightChangeChainService costWeightChangeChainService;
    @Resource
    private ICostWeightChangeSourceService costWeightChangeSourceService;

    /**
     * 分页查询成本单价变化记录
     */
    @PostMapping("/list")
    @ApiOperation(value = "分页查询成本单价变化记录", 
                  notes = "分页查询成本单价变化记录，返回所有匹配条件的成本单价变化记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "queryTO", value = "查询条件", required = true, dataType = "CostWeightChangeQueryTO", paramType = "body")
    })
    public R list(@RequestBody CostWeightChangeQueryTO queryTO) {
        try {
            IPage<CostWeightChangeSource> page = costWeightChangeQueryService.queryCostWeightChanges(queryTO);
            return R.data(new PageUtils(page));
        } catch (Exception e) {
            log.error("查询成本单价变化记录失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 分组分页查询成本单价变化记录
     */
    @PostMapping("/listGrouped")
    @ApiOperation(value = "分组分页查询成本单价变化记录", 
                  notes = "按照链路ID分组查询成本单价变化记录，同一链路ID下的所有变化记录会被合并为一条记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "queryTO", value = "查询条件", required = true, dataType = "CostWeightChangeQueryTO", paramType = "body")
    })
    public R listGrouped(@RequestBody CostWeightChangeQueryTO queryTO) {
        try {
            IPage<CostWeightChangeGroupVO> page = costWeightChangeQueryService.queryCostWeightChangesGrouped(queryTO);
            return R.data(new PageUtils(page));
        } catch (Exception e) {
            log.error("分组查询成本单价变化记录失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询成本单价变化记录详情
     */
    @GetMapping("/info/{id}")
    @ApiOperation(value = "根据ID查询成本单价变化记录详情", 
                  notes = "根据ID查询成本单价变化记录详情，返回指定ID的成本单价变化记录完整信息。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "成本单价变化记录ID", required = true, dataType = "Long", paramType = "path")
    })
    public R info(@PathVariable("id") Long id) {
        try {
            CostWeightChangeSource changeSource = costWeightChangeQueryService.getById(id);
            return R.data(changeSource);
        } catch (Exception e) {
            log.error("查询成本单价变化记录详情失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据源头订单ID查询连锁变化链路
     */
    @GetMapping("/chain/{sourceOrderId}")
    @ApiOperation(value = "根据源头订单ID查询连锁变化链路", 
                  notes = "根据源头订单ID查询连锁变化链路，返回与指定订单ID相关的所有连锁变化记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "sourceOrderId", value = "源头订单ID", required = true, dataType = "Long", paramType = "path")
    })
    public R chain(@PathVariable("sourceOrderId") Long sourceOrderId) {
        try {
            List<CostWeightChangeSource> chainChanges = costWeightChangeQueryService.queryChainChangesBySourceOrder(sourceOrderId);
            return R.data(chainChanges);
        } catch (Exception e) {
            log.error("查询连锁变化链路失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据库存ID查询所有相关变化
     */
    @GetMapping("/related/{stockId}")
    @ApiOperation(value = "根据库存ID查询所有相关变化", 
                  notes = "根据库存ID查询所有相关变化，包括直接变化和连锁变化。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "stockId", value = "库存ID", required = true, dataType = "Long", paramType = "path")
    })
    public R related(@PathVariable("stockId") Long stockId) {
        try {
            List<CostWeightChangeSource> relatedChanges = costWeightChangeQueryService.queryRelatedChangesByStockId(stockId);
            return R.data(relatedChanges);
        } catch (Exception e) {
            log.error("查询相关变化失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 构建连锁变化链路视图
     */
    @GetMapping("/chainView/{sourceOrderId}")
    @ApiOperation(value = "构建连锁变化链路视图", 
                  notes = "根据源头订单ID构建连锁变化链路视图，展示变化的完整链路信息。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "sourceOrderId", value = "源头订单ID", required = true, dataType = "Long", paramType = "path")
    })
    public R chainView(@PathVariable("sourceOrderId") Long sourceOrderId) {
        try {
            CostWeightChangeChainVO chainView = chainViewService.buildChainViewBySourceOrder(sourceOrderId);
            return R.data(chainView);
        } catch (Exception e) {
            log.error("构建连锁变化链路视图失败", e);
            return R.fail("构建失败：" + e.getMessage());
        }
    }
    
    /**
     * 查询显著成本变化记录
     */
    @GetMapping("/significant")
    @ApiOperation(value = "查询显著成本变化记录", 
                  notes = "查询显著成本变化记录，返回变化金额超过指定阈值的成本变化记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "threshold", value = "变化阈值", required = true, dataType = "BigDecimal", paramType = "query")
    })
    public R significant(@RequestParam BigDecimal threshold) {
        try {
            List<CostWeightChangeSource> significantChanges = costWeightChangeQueryService.querySignificantChanges(threshold);
            return R.data(significantChanges);
        } catch (Exception e) {
            log.error("查询显著成本变化记录失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据追踪事务ID查询整条链路上的所有变化记录
     */
    @GetMapping("/chain/listByTtid")
    @ApiOperation(value = "根据追踪事务ID查询整条链路上的所有变化记录", 
                  notes = "根据追踪事务ID查询整条链路上的所有变化记录，返回指定链路ID的所有变化记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "ttid", value = "追踪事务ID", required = true, dataType = "String", paramType = "query")
    })
    public R listByTtid(@RequestParam String ttid) {
        try {
            List<CostWeightChangeSource> changes = costWeightChangeChainService.queryChainByTtid(ttid);
            return R.data(changes);
        } catch (Exception e) {
            log.error("根据追踪事务ID查询变化记录失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据追踪事务ID查询整条链路的详细信息
     */
    @GetMapping("/chain/detailByTtid")
    @ApiOperation(value = "根据追踪事务ID查询整条链路的详细信息", 
                  notes = "根据追踪事务ID查询整条链路的详细信息，返回指定链路ID的详细变化信息。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "ttid", value = "追踪事务ID", required = true, dataType = "String", paramType = "query")
    })
    public R detailByTtid(@RequestParam String ttid) {
        try {
            ICostWeightChangeChainService.ChainDetailVO detailVO = costWeightChangeChainService.getChainDetail(ttid);
            if (detailVO == null) {
                return R.fail("未找到相关记录");
            }
            return R.data(detailVO);
        } catch (Exception e) {
            log.error("根据追踪事务ID查询链路详情失败", e);
            return R.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据追踪事务ID查询同一条链路上的所有变化
     */
    @GetMapping("/queryByTtid")
    @ApiOperation(value = "根据追踪事务ID查询同一条链路上的所有变化", 
                  notes = "根据追踪事务ID查询同一条链路上的所有变化，返回指定链路ID的所有变化记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "ttid", value = "追踪事务ID", required = true, dataType = "String", paramType = "query")
    })
    public R queryCostWeightChangeChainByTtid(@RequestParam String ttid) {
        log.info("根据追踪事务ID查询同一条链路上的所有变化，ttid: {}", ttid);

        try {
            QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ttid", ttid);
            queryWrapper.orderByAsc("operate_time");

            List<CostWeightChangeSource> changes = costWeightChangeSourceService.list(queryWrapper);

            log.info("查询到 {} 条变化记录", changes != null ? changes.size() : 0);

            return R.data(changes);
        } catch (Exception e) {
            log.error("根据追踪事务ID查询变化记录时发生错误，ttid: {}", ttid, e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }

    /**
     * 根据追踪事务ID分页查询同一条链路上的所有变化
     */
    @GetMapping("/queryPageByTtid")
    @ApiOperation(value = "根据追踪事务ID分页查询同一条链路上的所有变化", 
                  notes = "根据追踪事务ID分页查询同一条链路上的所有变化，返回指定链路ID的分页变化记录。")
    @ApiResponses({
        @ApiResponse(code = 200, message = "成功", response = R.class),
        @ApiResponse(code = 500, message = "服务器内部错误")
    })
    @ApiImplicitParams({
        @ApiImplicitParam(name = "ttid", value = "追踪事务ID", required = true, dataType = "String", paramType = "query"),
        @ApiImplicitParam(name = "page", value = "页码", required = false, defaultValue = "1", dataType = "Long", paramType = "query"),
        @ApiImplicitParam(name = "limit", value = "每页记录数", required = false, defaultValue = "10", dataType = "Long", paramType = "query")
    })
    public R queryCostWeightChangeChainPageByTtid(@RequestParam String ttid,
                                                  @RequestParam(defaultValue = "1") Long page,
                                                  @RequestParam(defaultValue = "10") Long limit) {
        log.info("根据追踪事务ID分页查询同一条链路上的所有变化，ttid: {}, page: {}, limit: {}", ttid, page, limit);

        try {
            QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ttid", ttid);
            queryWrapper.orderByAsc("operate_time");

            IPage<CostWeightChangeSource> pageUtils = costWeightChangeSourceService.queryPage(queryWrapper, page, limit);

            log.info("分页查询到 {} 条变化记录", pageUtils != null ? pageUtils.getTotal() : 0);

            return R.data(pageUtils);
        } catch (Exception e) {
            log.error("根据追踪事务ID分页查询变化记录时发生错误，ttid: {}", ttid, e);
            return R.fail("查询失败: " + e.getMessage());
        }
    }

    /**
     * 根据追踪事务ID导出同一条链路上的所有变化
     */
    @GetMapping("/exportByTtid")
    @ApiOperation(value = "根据追踪事务ID导出同一条链路上的所有变化", notes = "根据追踪事务ID导出同一条链路上的所有变化")
    public void exportCostWeightChangeChainByTtid(@RequestParam String ttid, HttpServletResponse response) {
        log.info("根据追踪事务ID导出同一条链路上的所有变化，ttid: {}", ttid);

        try {
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("成本变化链路_" + ttid, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ttid", ttid);
            queryWrapper.orderByAsc("operate_time");

            List<CostWeightChangeSource> changes = costWeightChangeSourceService.list(queryWrapper);

            log.info("导出 {} 条变化记录", changes != null ? changes.size() : 0);

            // 导出Excel逻辑
            // 这里需要实现具体的Excel导出逻辑，可以使用Apache POI或其他库
            // 为简化起见，这里只是示例

        } catch (Exception e) {
            log.error("根据追踪事务ID导出变化记录时发生错误，ttid: {}", ttid, e);
            // 处理导出错误
        }
    }
}